﻿using CodeStash.Addin.Core.Interfaces;
using EnvDTE;
using System.ComponentModel.Composition;
using CodeStash.Addin.Resources;

namespace CodeStash.Addin
{
    [Export(typeof(IDocumentService))]
    [PartCreationPolicy(CreationPolicy.Shared)]
    public class DocumentService : IDocumentService
    {
        EnvDTE.DTE provider;

        /// <summary>
        /// Initialize a new instance of <see cref="DocumentService"/>.
        /// </summary>
        public DocumentService()
        {
        }

        #region IDocumentService Members
        /// <summary>
        /// Set the DTE provider for this instance of the addin. This must be set before we can
        /// access any of the features present in this class.
        /// </summary>
        /// <typeparam name="T">The type of the DTE.</typeparam>
        /// <param name="provider">The actual DTE provider.</param>
        public void SetDTE<T>(T provider)
        {
            this.provider = provider as EnvDTE.DTE;
        }

        /// <summary>
        /// Has any text been selected?
        /// </summary>
        public bool TextSelected
        {
            get
            {
                return !string.IsNullOrWhiteSpace(SelectedText);
            }
        }

        /// <summary>
        /// Gets the selected text.
        /// </summary>
        public string SelectedText
        {
            get
            {
                TextSelection selection = GetSelectedText();
                if (selection == null) return string.Empty;
                return selection.Text;
            }
        }

        /// <summary>
        /// Insert the relevant text into the active document.
        /// </summary>
        /// <param name="textToInsert">The text to insert.</param>
        public void InsertText(string textToInsert)
        {
            if (provider == null || provider.ActiveDocument == null) return;

            if (provider.UndoContext.IsOpen)
                provider.UndoContext.Close();

            provider.UndoContext.Open(Messages.UndoContext);

            try
            {
                TextSelection sel = (TextSelection)provider.ActiveDocument.Selection;
                EditPoint startPoint = sel.TopPoint.CreateEditPoint();
                EditPoint endPoint = sel.BottomPoint.CreateEditPoint();

                if (sel.Text.Length == 0)
                {
                    endPoint.Insert(textToInsert);
                }
                else
                {
                    // We are replacing the text.
                    endPoint.ReplaceText(startPoint, textToInsert, (int)EnvDTE.vsEPReplaceTextOptions.vsEPReplaceTextAutoformat);
                }

                startPoint.SmartFormat(endPoint);
            }
            finally
            {
                // Ensure the context is closed.
                provider.UndoContext.Close();
            }
        }
        #endregion

        private TextSelection GetSelectedText()
        {
            if (provider == null || provider.ActiveDocument == null) return null;
            return (TextSelection)provider.ActiveDocument.Selection;
        }
    }
}